@tool
extends ICharacterComponent


class_name CharacterComponent
"""
角色组件,用于组织数据挂载其他子组件
"""


## 收到消息时触发
signal event_on_message(character: CharacterComponent, e: CharacterEvent)
## 收到行为通知时触发
signal event_on_effect(character: CharacterComponent, type: CharacterUnit.Effect, e: CharacterEvent)


class Message extends Object:
    var id: int = 0
    var e: CharacterEvent = null
    var processor: EventCenter = null


## 角色的所有属性字段
@export var meta_template: Dictionary[String, Attribute]:
    get:
        preload_template_meta()
        return __meta_template.items

## 类模板(从公共模板复制)
@export_storage var __meta_template: AttributeSet = null

## 公共模板
@export var unit_meta_resource: AttributeSet = null


## 对象数据(从类模板中复制一份,保证每个个体的数据独立)
var __meta: AttributeSet = null

var meta: AttributeSet:
    get:
        preload_template_meta()
        preload_meta()
        return __meta
    set(v):
        pass


## 消息计数器
var message_id: int = 0
## 消息队列
var message_queue: Array[Message] = []

## 挂载的事件和处理器
var processor: EventCenter = EventCenter.new()


func preload_template_meta() -> void:
    if __meta_template == null:
        if unit_meta_resource:
            __meta_template = unit_meta_resource.clone()
        else:
            __meta_template = AttributeSet.new()
    if unit_meta_resource:
        __meta_template.merge(unit_meta_resource)

func preload_meta() -> void:
    if __meta == null:
        __meta = __meta_template.clone()
        __meta.enable_notify()

func _ready() -> void:
    if Engine.is_editor_hint():
        preload_template_meta()
        # 编辑模式中剔除的旧属性
        for k in __meta_template.items.keys():
            if not unit_meta_resource.items.has(k):
                __meta_template.items.erase(k)
        return
    preload_template_meta()
    preload_meta()
    IComponent.ready(self)

func get_character() -> CharacterComponent:
    return self

func post(e: CharacterEvent, custom_processor: EventCenter = null) -> void:
    var m: Message = Message.new()
    m.e = e
    m.processor = custom_processor if custom_processor else processor
    message_id += 1
    m.id = message_id
    message_queue.append(m)

func proc() -> bool:
    var m: Message = message_queue.pop_front()
    if m:
        on_pre_message(m.e)
        if not m.e.is_canceled and is_instance_valid(m.processor):
            m.processor.on_event(self, m.e)
        return true
    return false

func _physics_process(delta: float) -> void:
    if Engine.is_editor_hint():
        return
    for i in range(10):
        if not proc():
            break

# 生成消息时预处理
func on_pre_message(e: CharacterEvent, custom_processor: EventCenter = null) -> void:
    event_on_message.emit(self, e)

# 消息处理完时后续处理
func on_end_message(type: CharacterUnit.Event, e: CharacterEvent) -> void:
    pass

# 处理消息
func on_message(e: CharacterEvent, custom_processor: EventCenter = null) -> bool:
    on_pre_message(e)

    var is_canceled: bool = false
    if not e.is_canceled:
        var p: EventCenter = custom_processor if custom_processor else processor
        is_canceled = p.on_event(self, e)
    return is_canceled

# 处理受到的效果
func on_effect(type: CharacterUnit.Effect, e: CharacterEvent) -> void:
    event_on_effect.emit(self, type, e)
